home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CU Amiga Super CD-ROM 1
/
CU Amiga Magazine CD-ROM Special Edition (1995)(EMAP Images)(GB)[Issue 1995-11].iso
/
Aminet
/
comm
/
tcp
/
AmigaTCP.lha
/
AmigaTCP
/
src
/
main.c
< prev
next >
Wrap
C/C++ Source or Header
|
1989-06-24
|
19KB
|
969 lines
/*
* Amiga version changes are
*
* Copyright (c)1987
* Louis A. Mamakos
*
* For non-commercial use only.
*/
/* Main network program - provides both client and server functions */
#define NSESSIONS 10 /* Maximum interactive client sessions */
#define HOSTNAMELEN 32 /* changed from 16 by Bdale 860812 */
#ifndef STARTUP
#ifdef AMIGA
#define STARTUP "s:net-sequence"
#else
#define STARTUP "/autoexec.net" /* File to read startup commands from */
#endif
#endif
#include <stdio.h>
#include "machdep.h"
#include "mbuf.h"
#include "netuser.h"
#include "timer.h"
#include "icmp.h"
#include "iface.h"
#include "ip.h"
#include "tcp.h"
#include "ftp.h"
#include "telnet.h"
#include "session.h"
#include "cmdparse.h"
#ifdef AMIGA
#include "amiga.h"
#else
#include "pc.h"
#endif
extern struct interface *ifaces;
struct session sessions[NSESSIONS];
struct session *current;
extern char major_rev[], minor_rev[];
int mode;
FILE *logfp;
#ifdef TRACE
#include "trace.h"
int32 trace;
#endif
char hostname[HOSTNAMELEN];
int32 aton();
int16 lport = 1001;
#ifdef AMIGA
char prompt[] = "\33[1;33mnet>\33[m "; /* make it standout and stuff */
#else
char prompt[] = "net> ";
#endif
char nospace[] = "No space!!\r\n"; /* Generic malloc fail message */
static char notval[] = "Not a valid TCB\r\n";
#ifndef MSDOS /* PC uses F-10 key always */
static char escape = 0x1d; /* default escape character is ^] */
#endif
/* Command lookup and branch table */
int go(),cmdmode(),dodigipeat(),
doipaddr(),dotelnet(),doexit(),doclose(),dohostname(),
doreset(),dotcpstat(),dotrace(),doescape(),dospeed(),dohelp(),
dowindow(),doroute(),doecho(),
dolog(),doipstat(),doicmpstat(),doetherstat(),memstat(),doarp(),
dosession(),doftp(),domss(),dostart(),dostop(),doattach(),
domycall(),dosmtptick(),doudpstat(),dottl(),dokiss(),dotcpkick(),
doeol();
#ifdef HAPN
int dohapnstat();
#endif HAPN
#ifdef AMIGADEVDRV
int DriverInit(), DriverShutdown(), CheckTcp();
#endif
static struct cmds cmds[] = {
/* The "go" command must be first */
"", go, 0, NULLCHAR, NULLCHAR,
"arp", doarp, 0, NULLCHAR, NULLCHAR,
"attach", doattach, 2,
"attach <hardware> <hw specific options>", NULLCHAR,
"close", doclose, 0, NULLCHAR, NULLCHAR,
#ifdef AX25
"digipeat", dodigipeat, 0, NULLCHAR, NULLCHAR,
#endif
#ifdef AMIGADEVDRV
"checktcp", CheckTcp, 0, NULLCHAR, NULLCHAR,
"driver", DriverInit, 0, NULLCHAR, NULLCHAR,
"driveroff", DriverShutdown, 0, NULLCHAR, NULLCHAR,
#endif
"echo", doecho, 0, NULLCHAR, NULLCHAR,
"eol", doeol, 0, NULLCHAR,
"eol options: unix, standard",
#ifndef MSDOS
"escape", doescape, 0, NULLCHAR, NULLCHAR,
#endif
#ifdef PC_EC
"etherstat", doetherstat, 0, NULLCHAR, NULLCHAR,
#endif PC_EC
"exit", doexit, 0, NULLCHAR, NULLCHAR,
"ftp", doftp, 2, "ftp <address>", NULLCHAR,
#ifdef HAPN
"hapnstat", dohapnstat, 0, NULLCHAR, NULLCHAR,
#endif HAPN
"help", dohelp, 0, NULLCHAR, NULLCHAR,
"hostname", dohostname, 0, NULLCHAR, NULLCHAR,
"log", dolog, 0, NULLCHAR, NULLCHAR,
"icmpstat", doicmpstat, 0, NULLCHAR, NULLCHAR,
"ipaddr", doipaddr, 0, NULLCHAR, NULLCHAR,
"ipstat", doipstat, 0, NULLCHAR, NULLCHAR,
#ifdef AX25
"kiss", dokiss, 0, NULLCHAR, NULLCHAR,
#endif
"smtp", dosmtptick, 0, NULLCHAR, NULLCHAR,
#ifndef AMIGA
"memstat", memstat, 0, NULLCHAR, NULLCHAR,
#endif
"mss", domss, 0, NULLCHAR, NULLCHAR,
#ifdef AX25
"mycall", domycall, 0, NULLCHAR, NULLCHAR,
#endif
"reset", doreset, 0, NULLCHAR, NULLCHAR,
"route", doroute, 0, NULLCHAR, NULLCHAR,
"session", dosession, 0, NULLCHAR, NULLCHAR,
"speed", dospeed, 0, NULLCHAR, NULLCHAR,
#ifdef SERVERS
"start", dostart, 2, "start <servername>",NULLCHAR,
"stop", dostop, 2, "stop <servername>", NULLCHAR,
#endif
"tcpstat", dotcpstat, 0, NULLCHAR, NULLCHAR,
"tcpkick", dotcpkick, 0, NULLCHAR, NULLCHAR,
"telnet", dotelnet, 2, "telnet <address>", NULLCHAR,
"trace", dotrace, 0, NULLCHAR, NULLCHAR,
"ttl", dottl, 0, NULLCHAR, NULLCHAR,
"udpstat", doudpstat, 0, NULLCHAR, NULLCHAR,
"window", dowindow, 0, NULLCHAR, NULLCHAR,
"?", dohelp, 0, NULLCHAR, NULLCHAR,
NULLCHAR, NULLFP, 0,
"Unknown command; type \"?\" for list", NULLCHAR,
};
/* "route" subcommands */
int doadd(),dodrop();
static struct cmds rtcmds[] = {
"add", doadd, 3,
"route add <dest addr>[/<bits>] <if name> [gateway] [metric]",
"Add failed",
"drop", dodrop, 2,
"route drop <dest addr>[/<bits>]",
"Not in table",
NULLCHAR, NULLFP, 0,
"route subcommands: add, drop",
NULLCHAR,
};
#ifdef SERVERS
/* "start" and "stop" subcommands */
int ftp_start(),smtp_start(),discard_start(),echo_start(),telnet_start();
static struct cmds startcmds[] = {
"discard", discard_start, 0, NULLCHAR, NULLCHAR,
"echo", echo_start, 0, NULLCHAR, NULLCHAR,
"ftp", ftp_start, 0, NULLCHAR, NULLCHAR,
"smtp", smtp_start, 0, NULLCHAR, NULLCHAR,
"telnet", telnet_start, 0, NULLCHAR, NULLCHAR,
NULLCHAR, NULLFP, 0,
"start options: discard, echo, ftp, smtp, telnet", NULLCHAR,
};
int ftp_stop(),smtp_stop(),echo_stop(),discard_stop(),telnet_stop();
static struct cmds stopcmds[] = {
"discard", discard_stop, 0, NULLCHAR, NULLCHAR,
"echo", echo_stop, 0, NULLCHAR, NULLCHAR,
"ftp", ftp_stop, 0, NULLCHAR, NULLCHAR,
"smtp", smtp_stop, 0, NULLCHAR, NULLCHAR,
"telnet", telnet_stop, 0, NULLCHAR, NULLCHAR,
NULLCHAR, NULLFP, 0,
"stop options: discard, echo, ftp, smtp, telnet", NULLCHAR,
};
#endif
main(argc,argv)
int argc;
char *argv[];
{
static char inbuf[BUFSIZ]; /* keep it off the stack */
int c;
char *ttybuf,*fgets();
int16 cnt;
int ttydriv();
int cmdparse();
void check_time();
FILE *fp;
struct interface *ifp;
#ifdef AMIGA
char *startup = STARTUP;
#endif
ioinit();
printf("KA9Q Internet Protocol Package, v%s.%s\n",major_rev,minor_rev);
#ifdef AMIGA
if (argc > 1)
startup = argv[1];
if((fp = fopen(startup,"r")) != NULLFILE){
while(fgets(inbuf,BUFSIZ,fp) != NULLCHAR){
printf(prompt); printf(inbuf);
cmdparse(cmds, inbuf);
}
fclose(fp);
} else
printf("Can't read inital commands from %s\n", startup);
#else
if((fp = fopen(STARTUP,"r")) != NULLFILE){
while(fgets(inbuf,BUFSIZ,fp) != NULLCHAR){
cmdparse(cmds,inbuf);
}
fclose(fp);
}
#endif
cmdmode();
smtpclinit(); /* arm SMTP background client timer */
/* Main commutator loop */
for(;;){
/* Process any keyboard input */
while((c = kbread()) != -1){
#ifdef MSDOS
/* c == -2 means the command escape key (F10) */
if(c == -2){
if(mode != CMD_MODE){
printf("\r\n");
cmdmode();
}
continue;
}
#else
if(c == escape && escape != 0 && mode != CMD_MODE) {
printf("\r\n");
cmdmode();
continue;
}
#endif
if((cnt = ttydriv(c,&ttybuf)) == 0)
continue;
switch(mode){
case CMD_MODE:
(void)cmdparse(cmds,ttybuf);
fflush(stdout);
break;
case CONV_MODE:
#ifndef MSDOS
if(ttybuf[0] == escape && escape != 0){
printf("\r\n");
cmdmode();
} else
#endif MSDOS
if(current->parse != NULLFP)
(*current->parse)(ttybuf,cnt);
break;
}
if(mode == CMD_MODE){
printf(prompt);
fflush(stdout);
}
}
/* Service the interfaces */
for(ifp = ifaces; ifp != NULLIF; ifp = ifp->next){
if(ifp->recv != NULLFP)
(*ifp->recv)(ifp);
}
/* Service the clock if it has ticked */
check_time();
#ifdef AMIGADEVDRV
/* check device driver open request */
check_driver();
CheckTcp();
#else
#ifdef MSDOS
/* Tell DoubleDos to let the other task run for awhile.
* If DoubleDos isn't active, this is a no-op
*/
giveup();
#else
/* Wait until interrupt, then do it all over again */
eihalt();
#endif
#endif AMIGADEVDRV
}
}
/* Enter command mode */
int
cmdmode()
{
if(mode != CMD_MODE){
mode = CMD_MODE;
cooked();
printf(prompt);
fflush(stdout);
}
return 0;
}
/* Select and display sessions */
static
dosession(argc,argv)
int argc;
char *argv[];
{
unsigned i;
struct session *s;
extern char *tcpstates[];
char *psocket();
if(argc < 2){
printf(" # Type Remote socket TCB State\r\n");
for(s=sessions;s < & sessions[NSESSIONS];s++){
switch(s->type){
case TELNET:
#ifndef AMIGA
printf("%c%-3d%Telnet %-23s%4x %-s\r\n",
(current == s)? '*':' ',
s - sessions,
psocket(&s->cb.telnet->tcb->conn.remote),
(int)s->cb.telnet->tcb,
tcpstates[s->cb.telnet->tcb->state]);
#else
printf("%c%-3d%Telnet %-23s%6lx %-s\r\n",
(current == s)? '*':' ',
s - sessions,
psocket(&s->cb.telnet->tcb->conn.remote),
(unsigned long)s->cb.telnet->tcb,
tcpstates[s->cb.telnet->tcb->state]);
#endif break;
case FTP:
#ifndef AMIGA
printf("%c%-3d%FTP %-23s%4x %-s\r\n",
(current == s)? '*':' ',
s - sessions,
psocket(&s->cb.ftp->control->conn.remote),
(int)s->cb.ftp->control,
tcpstates[s->cb.ftp->control->state]);
#else
printf("%c%-3d%FTP %-23s%6lx %-s\r\n",
(current == s)? '*':' ',
s - sessions,
psocket(&s->cb.ftp->control->conn.remote),
(unsigned long)s->cb.ftp->control,
tcpstates[s->cb.ftp->control->state]);
#endif
break;
}
}
return 0;
}
i = atoi(argv[1]);
if(i > NSESSIONS){
printf("Invalid session: %d\r\n",i);
return 1;
}
if(sessions[i].type == FREE){
printf("Inactive session: %d\r\n",i);
return 1;
}
current = &sessions[i];
go();
return 0;
}
/* Enter conversational mode with current session */
int
go()
{
void rcv_char(),r_ctl();
if(current == NULLSESSION || current->type == FREE)
return 0;
mode = CONV_MODE;
switch(current->type){
case TELNET:
if(current->cb.telnet->remote[TN_ECHO])
raw(); /* Re-establish raw mode if it was set */
rcv_char(current->cb.telnet->tcb,0); /* Get any pending input */
break;
case FTP:
r_ctl(current->cb.ftp->control,0);
break;
}
return 0;
}
#ifdef AX25
extern int digipeat;
dodigipeat(argc,argv)
int argc;
char *argv[];
{
if(argc == 1) {
printf("digipeat %s\r\n",digipeat ? "on" : "off");
} else {
if(strcmp(argv[1],"on") == 0)
digipeat = 1;
else
digipeat = 0;
}
}
#endif
static
doipaddr(argc,argv)
int argc;
char *argv[];
{
char *inet_ntoa();
if(argc < 2)
printf("%s\r\n",inet_ntoa(ip_addr));
else
ip_addr = aton(argv[1]);
return 0;
}
static
doexit(argc,argv)
int argc;
char *argv[];
{
iostop();
DriverShutdown();
exit(0);
}
static
doclose(argc,argv)
int argc;
char *argv[];
{
if(current == NULLSESSION){
printf("No current session\r\n");
return 0;
}
switch(current->type){
case TELNET:
close_tcp(current->cb.telnet->tcb);
break;
case FTP:
close_tcp(current->cb.ftp->control);
break;
}
return 0;
}
static
doreset(argc,argv)
int argc;
char *argv[];
{
long htol();
struct tcb *tcb;
if(argc < 2){
if(current == NULLSESSION){
printf("No current session\r\n");
return 1;
}
switch(current->type){
case TELNET:
tcb = current->cb.telnet->tcb;
break;
case FTP:
tcb = current->cb.ftp->control;
break;
}
} else
tcb = (struct tcb *)htol(argv[1]);
if(!tcpval(tcb)){
printf(notval);
return 1;
}
close_self(tcb,RESET);
return 0;
}
static
int
dotcpstat(argc,argv)
int argc;
char *argv[];
{
long htol();
register struct tcb *tcb;
if(argc < 2){
tcpstat();
} else {
tcb = (struct tcb *)htol(argv[1]);
if(tcpval(tcb))
state_tcp(tcb);
else
printf(notval);
}
return 0;
}
static
int
dotcpkick(argc,argv)
int argc;
char *argv[];
{
long htol();
register struct tcb *tcb;
void tcp_timeout();
if(argc < 2){
if(current == NULLSESSION){
printf("No current session\r\n");
return 1;
}
switch(current->type){
case TELNET:
tcb = current->cb.telnet->tcb;
break;
case FTP:
tcb = current->cb.ftp->control;
break;
}
} else
tcb = (struct tcb *)htol(argv[1]);
if(!tcpval(tcb)){
printf(notval);
return 1;
}
if(argc > 2){
/* Optional value for SRTT */
tcb->srtt = atoi(argv[2]);
}
/* Don't actually do anything unless something is pending */
if(tcb->sndcnt != 0){
tcb->retry = 0;
tcp_timeout((int *)tcb);
}
return 0;
}
static
int
dotrace(argc,argv)
int argc;
char *argv[];
{
long htol();
#ifdef TRACE
if(argc < 2)
printf("trace level 0x%08lx\r\n",trace);
else
trace = htol(argv[1]);
return 0;
#else
printf("Trace not enabled - recompile with TRACE defined\r\n");
#endif
}
static
dohostname(argc,argv)
int argc;
char *argv[];
{
char *strncpy();
if(argc < 2)
printf("%s\r\n",hostname);
else
strncpy(hostname,argv[1],HOSTNAMELEN);
return 0;
}
static
int
dolog(argc,argv)
int argc;
char *argv[];
{
char *strncpy();
#ifdef AMIGA
static char logname[45]; /* long enough for CON:10/10/300/300/title */
#else
static char logname[15];
#endif
if(argc < 2){
if(logfp)
printf("Logging to %s\r\n",logname);
else
printf("Logging off\r\n");
return 0;
}
if(logfp){
fclose(logfp);
logfp = NULLFILE;
}
if(strcmp(argv[1],"stop") != 0){
#ifdef AMIGA
strncpy(logname,argv[1],45);
#else
strncpy(logname,argv[1],15);
#endif
logfp = fopen(logname,"a+");
}
return 0;
}
#ifndef MSDOS
static
int
doescape(argc,argv)
int argc;
char *argv[];
{
if(argc < 2)
printf("0x%x\r\n",escape);
else
escape = *argv[1];
return 0;
}
#endif MSDOS
static
int
dohelp(argc,argv)
int argc;
char *argv[];
{
register struct cmds *cmdp;
int i,j;
printf("Main commands:\r\n");
for(i=0,cmdp = cmds;cmdp->name != NULL;cmdp++,i++){
printf("%s",cmdp->name);
if((i % 4) == 3)
printf("\r\n");
else {
for(j=strlen(cmdp->name);j < 16; j++)
putchar(' ');
}
}
if((i % 4) != 0)
printf("\r\n");
return 0;
}
static
int
domss(argc,argv)
int argc;
char *argv[];
{
if(argc < 2)
printf("%d\r\n",tcp_mss);
else
tcp_mss = atoi(argv[1]);
return 0;
}
static
int
dowindow(argc,argv)
int argc;
char *argv[];
{
if(argc < 2)
printf("%d\r\n",tcp_window);
else
tcp_window = atoi(argv[1]);
return 0;
}
static
int
dottl(argc,argv)
char *argv[];
{
if(argc < 2)
printf("%u\r\n",ip_ttl & 0xff);
else
ip_ttl = atoi(argv[1]);
return 0;
}
struct session *
newsession()
{
register int i;
for(i=0;i<NSESSIONS;i++)
if(sessions[i].type == FREE)
return &sessions[i];
return NULLSESSION;
}
freesession(s)
struct session *s;
{
if(s != NULLSESSION)
s->type = FREE;
}
/* Display and/or manipulate routing table */
int
doroute(argc,argv)
int argc;
char *argv[];
{
if(argc < 2){
dumproute();
return 0;
}
return subcmd(rtcmds,argc,argv);
}
/* Add an entry to the routing table
* E.g., "add 1.2.3.4 ax0 5.6.7.8 3"
*/
int
doadd(argc,argv)
int argc;
char *argv[];
{
struct interface *ifp;
int32 dest,gateway;
unsigned bits;
char *bitp,*index();
int metric;
if(strcmp(argv[1],"default") == 0){
dest = 0;
bits = 0;
} else {
dest = aton(argv[1]);
/* If IP address is followed by an optional slash and
* a length field, (e.g., 128.96/16) get it;
* otherwise assume a full 32-bit address
*/
if((bitp = index(argv[1],'/')) != NULLCHAR){
bitp++;
bits = atoi(bitp);
} else
bits = 32;
}
for(ifp=ifaces;ifp != NULLIF;ifp = ifp->next){
if(strcmp(argv[2],ifp->name) == 0)
break;
}
if(ifp == NULL){
printf("Interface \"%s\" unknown\r\n",argv[2]);
return 1;
}
if(argc > 3)
gateway = aton(argv[3]);
else
gateway = 0;
if(argc > 4)
metric = atoi(argv[4]);
else
metric = 0;
rt_add(dest,bits,gateway,metric,ifp);
return 0;
}
/* Drop an entry from the routing table
* E.g., "drop 128.96/16
*/
int
dodrop(argc,argv)
int argc;
char *argv[];
{
char *bitp,*index();
unsigned bits;
/* If IP address is followed by an optional slash and length field,
* (e.g., 128.96/16) get it; otherwise assume a full 32-bit address
*/
if((bitp = index(argv[1],'/')) != NULLCHAR){
bitp++;
bits = atoi(bitp);
} else
bits = 32;
return rt_drop(aton(argv[1]),bits);
}
#ifdef SERVERS
dostart(argc,argv)
int argc;
char *argv[];
{
return subcmd(startcmds,argc,argv);
}
dostop(argc,argv)
int argc;
char *argv[];
{
return subcmd(stopcmds,argc,argv);
}
#endif SERVERS
doecho(argc,argv)
int argc;
char *argv[];
{
extern int refuse_echo;
if(argc < 2){
if(refuse_echo)
printf("Refuse\r\n");
else
printf("Accept\r\n");
} else {
if(strcmp(argv[1],"refuse") == 0)
refuse_echo = 1;
else if(strcmp(argv[1],"accept") == 0)
refuse_echo = 0;
else
return -1;
}
return 0;
}
/* set for unix end of line for remote echo mode telnet */
doeol(argc,argv)
int argc;
char *argv[];
{
extern int unix_line_mode;
if(argc < 2){
if(unix_line_mode)
printf("Unix\r\n");
else
printf("Standard\r\n");
} else {
if(strcmp(argv[1],"unix") == 0)
unix_line_mode = 1;
else if(strcmp(argv[1],"standard") == 0)
unix_line_mode = 0;
else {
return -1;
}
}
return 0;
}
/* List of supported hardware devices */
#ifdef PC_EC
int ec_attach();
#endif
int asy_attach();
#ifdef PC100
int pc_attach();
#endif
#ifdef HAPN
int hapn_attach();
#endif
#ifdef NETROM
int netrom_attach();
#endif
struct cmds attab[] = {
#ifdef NETROM
/* NET/ROM virtual interface using companion asy interface in AX.25 mode */
"netrom", netrom_attach, 4,
"attach netrom <asy-intf> ax25 <label> [mtu [ upd-freq ]]",
"Could not attach NET/ROM virtual interface",
#endif
#ifdef PC_EC
/* 3-Com Ethernet interface */
"3c500", ec_attach, 7,
"attach 3c500 <address> <vector> arpa <label> <buffers> <mtu>",
"Could not attach 3c500",
#endif
/* Ordinary PC asynchronous adaptor */
"asy", asy_attach, 8,
"attach asy <address> <vector> slip|ax25 <label> <buffers> <mtu> <speed>",
"Could not attach asy",
#ifdef PC100
/* PACCOMM PC-100 8530 HDLC adaptor */
"pc100", pc_attach, 8,
"attach pc100 <address> <vector> ax25 <label> <buffers> <mtu> <speed>",
"Could not attach pc100",
#endif
#ifdef HAPN
/* Hamilton Area Packet Radio (HAPN) 8273 HDLC adaptor */
"hapn", hapn_attach, 8,
"attach hapn <address> <vector> ax25 <label> <rx bufsize> <mtu> csma|full",
"Could not attach hapn",
#endif
NULLCHAR, NULLFP, 0,
"Unknown device",
NULLCHAR,
};
/* Attach an interface
* Syntax: attach <hw type> <I/O address> <vector> <mode> <label> <bufsize> [<speed>]
*/
doattach(argc,argv)
int argc;
char *argv[];
{
return subcmd(attab,argc,argv);
}
int
dospeed(argc,argv)
int argc;
char *argv[];
{
int i;
if(argc < 3){
for(i=0;i < nasy; i++){
printf("%d: %d bps\r\n",i,asy[i].speed);
}
return 0;
}
i = atoi(argv[1]);
if(i >= nasy){
printf("Line %d out of range\r\n",i);
return 0;
}
asy_speed(i,atoi(argv[2]));
return i;
}
/* Log messages of the form
* Tue Jan 31 00:00:00 1987 44.64.0.7:1003 open FTP
*/
/*VARARGS2*/
log(tcb,fmt,arg1,arg2,arg3,arg4)
struct tcb *tcb;
char *fmt;
int arg1,arg2,arg3,arg4;
{
char *cp,*cp1,*ctime(),*index();
long t;
if(logfp == NULLFILE)
return;
time(&t);
cp = ctime(&t);
if((cp1 = index(cp,'\n')) != NULLCHAR)
*cp1 = '\0';
fprintf(logfp,"%s %s - ",cp,psocket(&tcb->conn.remote));
fprintf(logfp,fmt,arg1,arg2,arg3,arg4);
fprintf(logfp,"\n");
fflush(logfp);
}
/* Define null definitions for unused interfaces to avoid pulling in code
* from the library
*/
#ifndef ETHER
int ec_output() {}
int pether() {}
int gether() {}
char *ether_bdcst = NULLCHAR;
#endif ETHER
#ifndef AX25
int setcall() {}
int psax25() {}
struct ax25_addr ax25_bdcst,mycall;
#endif AX25